<html><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
  <title>Chapter 13. Test-Driven Development</title>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
  <link rel="stylesheet" href="docbook.css" tppabs="http://www.phpunit.de/manual/current/en/docbook.css" type="text/css"></link>
</head>
<body>

<div id="header">
  <h1>PHPUnit Manual</h1>

  <ul>
<li><a href="javascript:if(confirm('http://www.phpunit.de/manual/3.4/en/index.html  \n\nļδ Teleport Pro ȡأΪ ·ʼַõķΧ  \n\nҪӷϴ'))window.location='http://www.phpunit.de/manual/3.4/en/index.html'" tppabs="http://www.phpunit.de/manual/3.4/en/index.html">PHPUnit 3.4 <span><small>English</small></span></a></li><li><a href="javascript:if(confirm('http://www.phpunit.de/manual/3.3/en/index.html  \n\nļδ Teleport Pro ȡأΪ ·ʼַõķΧ  \n\nҪӷϴ'))window.location='http://www.phpunit.de/manual/3.3/en/index.html'" tppabs="http://www.phpunit.de/manual/3.3/en/index.html" class="active">PHPUnit 3.3 <span><small>English</small></span></a></li><li><a href="javascript:if(confirm('http://www.phpunit.de/manual/3.2/en/index.html  \n\nļδ Teleport Pro ȡأΪ ·ʼַõķΧ  \n\nҪӷϴ'))window.location='http://www.phpunit.de/manual/3.2/en/index.html'" tppabs="http://www.phpunit.de/manual/3.2/en/index.html">PHPUnit 3.2 <span><small>English</small></span></a></li><li><a href="javascript:if(confirm('http://www.phpunit.de/manual/3.1/en/index.html  \n\nļδ Teleport Pro ȡأΪ ·ʼַõķΧ  \n\nҪӷϴ'))window.location='http://www.phpunit.de/manual/3.1/en/index.html'" tppabs="http://www.phpunit.de/manual/3.1/en/index.html">PHPUnit 3.1 <span><small>English</small></span></a></li><li><a href="javascript:if(confirm('http://www.phpunit.de/manual/3.0/en/index.html  \n\nļδ Teleport Pro ȡأΪ ·ʼַõķΧ  \n\nҪӷϴ'))window.location='http://www.phpunit.de/manual/3.0/en/index.html'" tppabs="http://www.phpunit.de/manual/3.0/en/index.html">PHPUnit 3.0 <span><small>English</small></span></a></li><li><a href="javascript:if(confirm('http://www.phpunit.de/manual/2.3/en/index.html  \n\nļδ Teleport Pro ȡأΪ ·ʼַõķΧ  \n\nҪӷϴ'))window.location='http://www.phpunit.de/manual/2.3/en/index.html'" tppabs="http://www.phpunit.de/manual/2.3/en/index.html">PHPUnit 2.3 <span><small>English</small></span></a></li><li><a href="javascript:if(confirm('http://www.phpunit.de/manual/3.3/ja/index.html  \n\nļδ Teleport Pro ȡأΪ ·ʼַõķΧ  \n\nҪӷϴ'))window.location='http://www.phpunit.de/manual/3.3/ja/index.html'" tppabs="http://www.phpunit.de/manual/3.3/ja/index.html">PHPUnit 3.3 <span><small>Japanese</small></span></a></li><li><a href="javascript:if(confirm('http://www.phpunit.de/manual/3.2/ja/index.html  \n\nļδ Teleport Pro ȡأΪ ·ʼַõķΧ  \n\nҪӷϴ'))window.location='http://www.phpunit.de/manual/3.2/ja/index.html'" tppabs="http://www.phpunit.de/manual/3.2/ja/index.html">PHPUnit 3.2 <span><small>Japanese</small></span></a></li><li><a href="javascript:if(confirm('http://www.phpunit.de/manual/3.1/ja/index.html  \n\nļδ Teleport Pro ȡأΪ ·ʼַõķΧ  \n\nҪӷϴ'))window.location='http://www.phpunit.de/manual/3.1/ja/index.html'" tppabs="http://www.phpunit.de/manual/3.1/ja/index.html">PHPUnit 3.1 <span><small>Japanese</small></span></a></li><li><a href="javascript:if(confirm('http://www.phpunit.de/manual/3.0/ja/index.html  \n\nļδ Teleport Pro ȡأΪ ·ʼַõķΧ  \n\nҪӷϴ'))window.location='http://www.phpunit.de/manual/3.0/ja/index.html'" tppabs="http://www.phpunit.de/manual/3.0/ja/index.html">PHPUnit 3.0 <span><small>Japanese</small></span></a></li><li><a href="javascript:if(confirm('http://www.phpunit.de/manual/2.3/ja/index.html  \n\nļδ Teleport Pro ȡأΪ ·ʼַõķΧ  \n\nҪӷϴ'))window.location='http://www.phpunit.de/manual/2.3/ja/index.html'" tppabs="http://www.phpunit.de/manual/2.3/ja/index.html">PHPUnit 2.3 <span><small>Japanese</small></span></a></li><li><a href="javascript:if(confirm('http://www.phpunit.de/manual/2.3/de/index.html  \n\nļδ Teleport Pro ȡأΪ ·ʼַõķΧ  \n\nҪӷϴ'))window.location='http://www.phpunit.de/manual/2.3/de/index.html'" tppabs="http://www.phpunit.de/manual/2.3/de/index.html">PHPUnit 2.3 <span><small>German</small></span></a></li>
  </ul>
</div>
<div class="colmask leftmenu">
  <div class="colleft">
    <div class="col1">
      <table border="0" width="100%">
        <tr>
          <td align="left"><a accesskey="p" href="testing-practices.html" tppabs="http://www.phpunit.de/manual/current/en/testing-practices.html">Prev</a></td>
          <td align="right"><a accesskey="n" href="behaviour-driven-development.html" tppabs="http://www.phpunit.de/manual/current/en/behaviour-driven-development.html">Next</a></td>
        </tr>
      </table>
<div class="chapter" title="Chapter 13. Test-Driven Development"><div class="titlepage"><div><div><h2 class="title"><a id="test-driven-development"></a>Chapter 13. Test-Driven Development</h2></div></div></div><p>
    <a id="id2566038" class="indexterm"></a>
    <a id="id2566045" class="indexterm"></a>
    <a id="id2566052" class="indexterm"></a>
    <a id="id2566059" class="indexterm"></a>
    <a id="id2566065" class="indexterm"></a>

    Unit Tests are a vital part of several software development practices
    and processes such as Test-First Programming,
    <a class="ulink" href="javascript:if(confirm('http://en.wikipedia.org/wiki/Extreme_Programming  \n\nļδ Teleport Pro ȡأΪ ·ʼַõķΧ  \n\nҪӷϴ'))window.location='http://en.wikipedia.org/wiki/Extreme_Programming'" tppabs="http://en.wikipedia.org/wiki/Extreme_Programming" target="_top">Extreme Programming</a>,
    and <a class="ulink" href="javascript:if(confirm('http://en.wikipedia.org/wiki/Test-driven_development  \n\nļδ Teleport Pro ȡأΪ ·ʼַõķΧ  \n\nҪӷϴ'))window.location='http://en.wikipedia.org/wiki/Test-driven_development'" tppabs="http://en.wikipedia.org/wiki/Test-driven_development" target="_top">Test-Driven Development</a>.
    They also allow for <a class="ulink" href="javascript:if(confirm('http://en.wikipedia.org/wiki/Design_by_Contract  \n\nļδ Teleport Pro ȡأΪ ·ʼַõķΧ  \n\nҪӷϴ'))window.location='http://en.wikipedia.org/wiki/Design_by_Contract'" tppabs="http://en.wikipedia.org/wiki/Design_by_Contract" target="_top">Design-by-Contract</a>
    in programming languages that do not support this methodology with
    language constructs.
  </p><p>
    You can use PHPUnit to write tests once you are done programming.
    However, the sooner a test is written after an error has been introduced,
    the more valuable the test is. So instead of writing tests months after
    the code is "complete", we can write tests days or hours or minutes after
    the possible introduction of a defect. Why stop there? Why not write the
    tests a little before the possible introduction of a defect?
  </p><p>
    Test-First Programming, which is part of Extreme Programming and
    Test-Driven Development, builds upon this idea and takes it to the
    extreme. With today's computational power, we have the opportunity to
    run thousands of tests thousands of times per day. We can use the
    feedback from all of these tests to program in small steps, each of
    which carries with it the assurance of a new automated test in addition
    to all the tests that have come before. The tests are like pitons,
    assuring you that, no matter what happens, once you have made progress
    you can only fall so far.
  </p><p>
    When you first write the test it cannot possibly run, because you are
    calling on objects and methods that have not been programmed yet. This
    might feel strange at first, but after a while you will get used to it.
    Think of Test-First Programming as a pragmatic approach to following the
    object-oriented programming principle of programming to an interface
    instead of programming to an implementation: while you are writing the
    test you are thinking about the interface of the object you are
    testing -- what does this object look like from the outside. When you
    go to make the test really work, you are thinking about pure
    implementation. The interface is fixed by the failing test.
  </p><div class="blockquote"><table border="0" width="100%" cellspacing="0" cellpadding="0" class="blockquote" summary="Block quote"><tr><td width="10%" valign="top"> </td><td width="80%" valign="top"><p>
      The point of <a class="ulink" href="javascript:if(confirm('http://en.wikipedia.org/wiki/Test-driven_development  \n\nļδ Teleport Pro ȡأΪ ·ʼַõķΧ  \n\nҪӷϴ'))window.location='http://en.wikipedia.org/wiki/Test-driven_development'" tppabs="http://en.wikipedia.org/wiki/Test-driven_development" target="_top">Test-Driven Development</a>
      is to drive out the functionality the software actually needs, rather
      than what the programmer thinks it probably ought to have. The way it
      does this seems at first counterintuitive, if not downright silly, but
      it not only makes sense, it also quickly becomes a natural and elegant
      way to develop software.
    </p></td><td width="10%" valign="top"> </td></tr><tr><td width="10%" valign="top"> </td><td colspan="2" align="right" valign="top">--<span class="attribution">Dan North</span></td></tr></table></div><p>
    What follows is necessarily an abbreviated introduction to Test-Driven
    Development. You can explore the topic further in other books, such as
    <span class="emphasis"><em>Test-Driven Development</em></span> <a class="xref" href="appendixes.bibliography.html#Beck2002" tppabs="http://www.phpunit.de/manual/current/en/appendixes.bibliography.html#Beck2002" title="Test Driven Development by Example">[<abbr class="abbrev">Beck2002</abbr>]</a>
    by Kent Beck or Dave Astels' <span class="emphasis"><em>A Practical Guide to Test-Driven
    Development</em></span> <a class="xref" href="appendixes.bibliography.html#Astels2003" tppabs="http://www.phpunit.de/manual/current/en/appendixes.bibliography.html#Astels2003" title="Test Driven Development">[<abbr class="abbrev">Astels2003</abbr>]</a>.
  </p><div class="section" title="BankAccount Example"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a id="test-driven-development.bankaccount-example"></a>BankAccount Example</h2></div></div></div><p>
      In this section, we will look at the example of a class that represents
      a bank account. The contract for the <code class="literal">BankAccount</code>
      class not only requires methods to get and set the bank account's
      balance, as well as methods to deposit and withdraw money. It also
      specifies the following two conditions that must be ensured:
    </p><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><p>The bank account's initial balance must be zero.</p></li><li class="listitem"><p>The bank account's balance cannot become negative.</p></li></ul></div><p>
      We write the tests for the <code class="literal">BankAccount</code> class before we
      write the code for the class itself. We use the contract conditions as the
      basis for the tests and name the test methods accordingly, as shown in
      <a class="xref" href="test-driven-development.html#test-driven-development.bankaccount-example.examples.BankAccountTest.php" tppabs="http://www.phpunit.de/manual/current/en/test-driven-development.html#test-driven-development.bankaccount-example.examples.BankAccountTest.php" title="Example 13.1: Tests for the BankAccount class">Example 13.1</a>.
    </p><div class="example"><a id="test-driven-development.bankaccount-example.examples.BankAccountTest.php"></a><p class="title"><b>Example 13.1: Tests for the BankAccount class</b></p><div class="example-contents"><pre class="programlisting"><code><span class="default">&lt;?php</span><br /><span class="keyword">require_once</span><span class="default">&nbsp;</span><span class="string">'PHPUnit/Framework.php'</span><span class="keyword">;</span><br /><span class="keyword">require_once</span><span class="default">&nbsp;</span><span class="string">'BankAccount.php'</span><span class="keyword">;</span><br />&nbsp;<br /><span class="keyword">class</span><span class="default">&nbsp;</span><span class="default">BankAccountTest</span><span class="default">&nbsp;</span><span class="keyword">extends</span><span class="default">&nbsp;</span><span class="default">PHPUnit_Framework_TestCase</span><br /><span class="keyword">{</span><br /><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">protected</span><span class="default">&nbsp;</span><span class="default">$ba</span><span class="keyword">;</span><br />&nbsp;<br /><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">protected</span><span class="default">&nbsp;</span><span class="keyword">function</span><span class="default">&nbsp;</span><span class="default">setUp</span><span class="keyword">(</span><span class="keyword">)</span><br /><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">{</span><br /><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">$this</span><span class="keyword">-&gt;</span><span class="default">ba</span><span class="default">&nbsp;</span><span class="keyword">=</span><span class="default">&nbsp;</span><span class="keyword">new</span><span class="default">&nbsp;</span><span class="default">BankAccount</span><span class="keyword">;</span><br /><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">}</span><br />&nbsp;<br /><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">public</span><span class="default">&nbsp;</span><span class="keyword">function</span><span class="default">&nbsp;</span><span class="default">testBalanceIsInitiallyZero</span><span class="keyword">(</span><span class="keyword">)</span><br /><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">{</span><br /><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">$this</span><span class="keyword">-&gt;</span><span class="default">assertEquals</span><span class="keyword">(</span><span class="default">0</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="default">$this</span><span class="keyword">-&gt;</span><span class="default">ba</span><span class="keyword">-&gt;</span><span class="default">getBalance</span><span class="keyword">(</span><span class="keyword">)</span><span class="keyword">)</span><span class="keyword">;</span><br /><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">}</span><br />&nbsp;<br /><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">public</span><span class="default">&nbsp;</span><span class="keyword">function</span><span class="default">&nbsp;</span><span class="default">testBalanceCannotBecomeNegative</span><span class="keyword">(</span><span class="keyword">)</span><br /><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">{</span><br /><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">try</span><span class="default">&nbsp;</span><span class="keyword">{</span><br /><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">$this</span><span class="keyword">-&gt;</span><span class="default">ba</span><span class="keyword">-&gt;</span><span class="default">withdrawMoney</span><span class="keyword">(</span><span class="default">1</span><span class="keyword">)</span><span class="keyword">;</span><br /><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">}</span><br />&nbsp;<br /><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">catch</span><span class="default">&nbsp;</span><span class="keyword">(</span><span class="default">BankAccountException</span><span class="default">&nbsp;</span><span class="default">$e</span><span class="keyword">)</span><span class="default">&nbsp;</span><span class="keyword">{</span><br /><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">$this</span><span class="keyword">-&gt;</span><span class="default">assertEquals</span><span class="keyword">(</span><span class="default">0</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="default">$this</span><span class="keyword">-&gt;</span><span class="default">ba</span><span class="keyword">-&gt;</span><span class="default">getBalance</span><span class="keyword">(</span><span class="keyword">)</span><span class="keyword">)</span><span class="keyword">;</span><br />&nbsp;<br /><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">return</span><span class="keyword">;</span><br /><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">}</span><br />&nbsp;<br /><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">$this</span><span class="keyword">-&gt;</span><span class="default">fail</span><span class="keyword">(</span><span class="keyword">)</span><span class="keyword">;</span><br /><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">}</span><br />&nbsp;<br /><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">public</span><span class="default">&nbsp;</span><span class="keyword">function</span><span class="default">&nbsp;</span><span class="default">testBalanceCannotBecomeNegative2</span><span class="keyword">(</span><span class="keyword">)</span><br /><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">{</span><br /><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">try</span><span class="default">&nbsp;</span><span class="keyword">{</span><br /><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">$this</span><span class="keyword">-&gt;</span><span class="default">ba</span><span class="keyword">-&gt;</span><span class="default">depositMoney</span><span class="keyword">(</span><span class="keyword">-</span><span class="default">1</span><span class="keyword">)</span><span class="keyword">;</span><br /><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">}</span><br />&nbsp;<br /><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">catch</span><span class="default">&nbsp;</span><span class="keyword">(</span><span class="default">BankAccountException</span><span class="default">&nbsp;</span><span class="default">$e</span><span class="keyword">)</span><span class="default">&nbsp;</span><span class="keyword">{</span><br /><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">$this</span><span class="keyword">-&gt;</span><span class="default">assertEquals</span><span class="keyword">(</span><span class="default">0</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="default">$this</span><span class="keyword">-&gt;</span><span class="default">ba</span><span class="keyword">-&gt;</span><span class="default">getBalance</span><span class="keyword">(</span><span class="keyword">)</span><span class="keyword">)</span><span class="keyword">;</span><br />&nbsp;<br /><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">return</span><span class="keyword">;</span><br /><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">}</span><br />&nbsp;<br /><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">$this</span><span class="keyword">-&gt;</span><span class="default">fail</span><span class="keyword">(</span><span class="keyword">)</span><span class="keyword">;</span><br /><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">}</span><br /><span class="keyword">}</span><br /><span class="default">?&gt;</span><br /></code></pre></div></div><br class="example-break"></br><p>
      We now write the minimal amount of code needed for the first test,
      <code class="literal">testBalanceIsInitiallyZero()</code>, to pass. In our
      example this amounts to implementing the <code class="literal">getBalance()</code>
      method of the <code class="literal">BankAccount</code> class, as shown in
      <a class="xref" href="test-driven-development.html#test-driven-development.bankaccount-example.examples.BankAccount.php" tppabs="http://www.phpunit.de/manual/current/en/test-driven-development.html#test-driven-development.bankaccount-example.examples.BankAccount.php" title="Example 13.2: Code needed for the testBalanceIsInitiallyZero() test to pass">Example 13.2</a>.
    </p><div class="example"><a id="test-driven-development.bankaccount-example.examples.BankAccount.php"></a><p class="title"><b>Example 13.2: Code needed for the testBalanceIsInitiallyZero() test to pass</b></p><div class="example-contents"><pre class="programlisting"><code><span class="default">&lt;?php</span><br /><span class="keyword">class</span><span class="default">&nbsp;</span><span class="default">BankAccount</span><br /><span class="keyword">{</span><br /><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">protected</span><span class="default">&nbsp;</span><span class="default">$balance</span><span class="default">&nbsp;</span><span class="keyword">=</span><span class="default">&nbsp;</span><span class="default">0</span><span class="keyword">;</span><br />&nbsp;<br /><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">public</span><span class="default">&nbsp;</span><span class="keyword">function</span><span class="default">&nbsp;</span><span class="default">getBalance</span><span class="keyword">(</span><span class="keyword">)</span><br /><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">{</span><br /><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">return</span><span class="default">&nbsp;</span><span class="default">$this</span><span class="keyword">-&gt;</span><span class="default">balance</span><span class="keyword">;</span><br /><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">}</span><br /><span class="keyword">}</span><br /><span class="default">?&gt;</span><br /></code></pre></div></div><br class="example-break"></br><p>
      The test for the first contract condition now passes, but the tests for
      the second contract condition fail because we have yet to implement the
      methods that these tests call.
    </p><pre class="screen"><strong class="userinput"><code>phpunit BankAccountTest</code></strong>
PHPUnit 3.3.0 by Sebastian Bergmann.

.
Fatal error: Call to undefined method BankAccount::withdrawMoney()</pre><p>
      For the tests that ensure the second contract condition to pass, we now
      need to implement the <code class="literal">withdrawMoney()</code>,
      <code class="literal">depositMoney()</code>, and <code class="literal">setBalance()</code>
      methods, as shown in
      <a class="xref" href="test-driven-development.html#test-driven-development.bankaccount-example.examples.BankAccount2.php" tppabs="http://www.phpunit.de/manual/current/en/test-driven-development.html#test-driven-development.bankaccount-example.examples.BankAccount2.php" title="Example 13.3: The complete BankAccount class">Example 13.3</a>.
      These methods are written in a such a way that they raise an
      <code class="literal">BankAccountException</code> when they are called with
      illegal values that would violate the contract conditions.
    </p><div class="example"><a id="test-driven-development.bankaccount-example.examples.BankAccount2.php"></a><p class="title"><b>Example 13.3: The complete BankAccount class</b></p><div class="example-contents"><pre class="programlisting"><code><span class="default">&lt;?php</span><br /><span class="keyword">class</span><span class="default">&nbsp;</span><span class="default">BankAccount</span><br /><span class="keyword">{</span><br /><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">protected</span><span class="default">&nbsp;</span><span class="default">$balance</span><span class="default">&nbsp;</span><span class="keyword">=</span><span class="default">&nbsp;</span><span class="default">0</span><span class="keyword">;</span><br />&nbsp;<br /><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">public</span><span class="default">&nbsp;</span><span class="keyword">function</span><span class="default">&nbsp;</span><span class="default">getBalance</span><span class="keyword">(</span><span class="keyword">)</span><br /><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">{</span><br /><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">return</span><span class="default">&nbsp;</span><span class="default">$this</span><span class="keyword">-&gt;</span><span class="default">balance</span><span class="keyword">;</span><br /><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">}</span><br />&nbsp;<br /><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">protected</span><span class="default">&nbsp;</span><span class="keyword">function</span><span class="default">&nbsp;</span><span class="default">setBalance</span><span class="keyword">(</span><span class="default">$balance</span><span class="keyword">)</span><br /><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">{</span><br /><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">if</span><span class="default">&nbsp;</span><span class="keyword">(</span><span class="default">$balance</span><span class="default">&nbsp;</span><span class="default">&gt;=</span><span class="default">&nbsp;</span><span class="default">0</span><span class="keyword">)</span><span class="default">&nbsp;</span><span class="keyword">{</span><br /><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">$this</span><span class="keyword">-&gt;</span><span class="default">balance</span><span class="default">&nbsp;</span><span class="keyword">=</span><span class="default">&nbsp;</span><span class="default">$balance</span><span class="keyword">;</span><br /><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">}</span><span class="default">&nbsp;</span><span class="keyword">else</span><span class="default">&nbsp;</span><span class="keyword">{</span><br /><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">throw</span><span class="default">&nbsp;</span><span class="keyword">new</span><span class="default">&nbsp;</span><span class="default">BankAccountException</span><span class="keyword">;</span><br /><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">}</span><br /><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">}</span><br />&nbsp;<br /><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">public</span><span class="default">&nbsp;</span><span class="keyword">function</span><span class="default">&nbsp;</span><span class="default">depositMoney</span><span class="keyword">(</span><span class="default">$balance</span><span class="keyword">)</span><br /><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">{</span><br /><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">$this</span><span class="keyword">-&gt;</span><span class="default">setBalance</span><span class="keyword">(</span><span class="default">$this</span><span class="keyword">-&gt;</span><span class="default">getBalance</span><span class="keyword">(</span><span class="keyword">)</span><span class="default">&nbsp;</span><span class="keyword">+</span><span class="default">&nbsp;</span><span class="default">$balance</span><span class="keyword">)</span><span class="keyword">;</span><br />&nbsp;<br /><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">return</span><span class="default">&nbsp;</span><span class="default">$this</span><span class="keyword">-&gt;</span><span class="default">getBalance</span><span class="keyword">(</span><span class="keyword">)</span><span class="keyword">;</span><br /><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">}</span><br />&nbsp;<br /><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">public</span><span class="default">&nbsp;</span><span class="keyword">function</span><span class="default">&nbsp;</span><span class="default">withdrawMoney</span><span class="keyword">(</span><span class="default">$balance</span><span class="keyword">)</span><br /><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">{</span><br /><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">$this</span><span class="keyword">-&gt;</span><span class="default">setBalance</span><span class="keyword">(</span><span class="default">$this</span><span class="keyword">-&gt;</span><span class="default">getBalance</span><span class="keyword">(</span><span class="keyword">)</span><span class="default">&nbsp;</span><span class="keyword">-</span><span class="default">&nbsp;</span><span class="default">$balance</span><span class="keyword">)</span><span class="keyword">;</span><br />&nbsp;<br /><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">return</span><span class="default">&nbsp;</span><span class="default">$this</span><span class="keyword">-&gt;</span><span class="default">getBalance</span><span class="keyword">(</span><span class="keyword">)</span><span class="keyword">;</span><br /><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">}</span><br /><span class="keyword">}</span><br /><span class="default">?&gt;</span><br /></code></pre></div></div><br class="example-break"></br><p>
      The tests that ensure the second contract condition now pass, too:
    </p><pre class="screen"><strong class="userinput"><code>phpunit BankAccountTest</code></strong>
PHPUnit 3.3.0 by Sebastian Bergmann.

...

Time: 0 seconds


OK (3 tests, 3 assertions)</pre><p>
      <a id="id2567343" class="indexterm"></a>

      Alternatively, you can use the static assertion methods provided by the
      <code class="literal">PHPUnit_Framework_Assert</code> class to write the contract
      conditions as design-by-contract style assertions into your code, as
      shown in <a class="xref" href="test-driven-development.html#test-driven-development.bankaccount-example.examples.BankAccount3.php" tppabs="http://www.phpunit.de/manual/current/en/test-driven-development.html#test-driven-development.bankaccount-example.examples.BankAccount3.php" title="Example 13.4: The BankAccount class with Design-by-Contract assertions">Example 13.4</a>.
      When one of these assertions fails, an
      <code class="literal">PHPUnit_Framework_AssertionFailedError</code> exception
      will be raised. With this approach, you write less code for the contract
      condition checks and the tests become more readable. However, you add a
      runtime dependency on PHPUnit to your project.
    </p><div class="example"><a id="test-driven-development.bankaccount-example.examples.BankAccount3.php"></a><p class="title"><b>Example 13.4: The BankAccount class with Design-by-Contract assertions</b></p><div class="example-contents"><pre class="programlisting"><code><span class="default">&lt;?php</span><br /><span class="keyword">require_once</span><span class="default">&nbsp;</span><span class="string">'PHPUnit/Framework.php'</span><span class="keyword">;</span><br />&nbsp;<br /><span class="keyword">class</span><span class="default">&nbsp;</span><span class="default">BankAccount</span><br /><span class="keyword">{</span><br /><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">private</span><span class="default">&nbsp;</span><span class="default">$balance</span><span class="default">&nbsp;</span><span class="keyword">=</span><span class="default">&nbsp;</span><span class="default">0</span><span class="keyword">;</span><br />&nbsp;<br /><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">public</span><span class="default">&nbsp;</span><span class="keyword">function</span><span class="default">&nbsp;</span><span class="default">getBalance</span><span class="keyword">(</span><span class="keyword">)</span><br /><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">{</span><br /><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">return</span><span class="default">&nbsp;</span><span class="default">$this</span><span class="keyword">-&gt;</span><span class="default">balance</span><span class="keyword">;</span><br /><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">}</span><br />&nbsp;<br /><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">protected</span><span class="default">&nbsp;</span><span class="keyword">function</span><span class="default">&nbsp;</span><span class="default">setBalance</span><span class="keyword">(</span><span class="default">$balance</span><span class="keyword">)</span><br /><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">{</span><br /><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">PHPUnit_Framework_Assert</span><span class="keyword">::</span><span class="default">assertTrue</span><span class="keyword">(</span><span class="default">$balance</span><span class="default">&nbsp;</span><span class="default">&gt;=</span><span class="default">&nbsp;</span><span class="default">0</span><span class="keyword">)</span><span class="keyword">;</span><br />&nbsp;<br /><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">$this</span><span class="keyword">-&gt;</span><span class="default">balance</span><span class="default">&nbsp;</span><span class="keyword">=</span><span class="default">&nbsp;</span><span class="default">$balance</span><span class="keyword">;</span><br /><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">}</span><br />&nbsp;<br /><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">public</span><span class="default">&nbsp;</span><span class="keyword">function</span><span class="default">&nbsp;</span><span class="default">depositMoney</span><span class="keyword">(</span><span class="default">$amount</span><span class="keyword">)</span><br /><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">{</span><br /><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">PHPUnit_Framework_Assert</span><span class="keyword">::</span><span class="default">assertTrue</span><span class="keyword">(</span><span class="default">$amount</span><span class="default">&nbsp;</span><span class="default">&gt;=</span><span class="default">&nbsp;</span><span class="default">0</span><span class="keyword">)</span><span class="keyword">;</span><br />&nbsp;<br /><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">$this</span><span class="keyword">-&gt;</span><span class="default">setBalance</span><span class="keyword">(</span><span class="default">$this</span><span class="keyword">-&gt;</span><span class="default">getBalance</span><span class="keyword">(</span><span class="keyword">)</span><span class="default">&nbsp;</span><span class="keyword">+</span><span class="default">&nbsp;</span><span class="default">$amount</span><span class="keyword">)</span><span class="keyword">;</span><br />&nbsp;<br /><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">return</span><span class="default">&nbsp;</span><span class="default">$this</span><span class="keyword">-&gt;</span><span class="default">getBalance</span><span class="keyword">(</span><span class="keyword">)</span><span class="keyword">;</span><br /><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">}</span><br />&nbsp;<br /><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">public</span><span class="default">&nbsp;</span><span class="keyword">function</span><span class="default">&nbsp;</span><span class="default">withdrawMoney</span><span class="keyword">(</span><span class="default">$amount</span><span class="keyword">)</span><br /><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">{</span><br /><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">PHPUnit_Framework_Assert</span><span class="keyword">::</span><span class="default">assertTrue</span><span class="keyword">(</span><span class="default">$amount</span><span class="default">&nbsp;</span><span class="default">&gt;=</span><span class="default">&nbsp;</span><span class="default">0</span><span class="keyword">)</span><span class="keyword">;</span><br /><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">PHPUnit_Framework_Assert</span><span class="keyword">::</span><span class="default">assertTrue</span><span class="keyword">(</span><span class="default">$this</span><span class="keyword">-&gt;</span><span class="default">balance</span><span class="default">&nbsp;</span><span class="default">&gt;=</span><span class="default">&nbsp;</span><span class="default">$amount</span><span class="keyword">)</span><span class="keyword">;</span><br />&nbsp;<br /><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">$this</span><span class="keyword">-&gt;</span><span class="default">setBalance</span><span class="keyword">(</span><span class="default">$this</span><span class="keyword">-&gt;</span><span class="default">getBalance</span><span class="keyword">(</span><span class="keyword">)</span><span class="default">&nbsp;</span><span class="keyword">-</span><span class="default">&nbsp;</span><span class="default">$amount</span><span class="keyword">)</span><span class="keyword">;</span><br />&nbsp;<br /><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">return</span><span class="default">&nbsp;</span><span class="default">$this</span><span class="keyword">-&gt;</span><span class="default">getBalance</span><span class="keyword">(</span><span class="keyword">)</span><span class="keyword">;</span><br /><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">}</span><br /><span class="keyword">}</span><br /><span class="default">?&gt;</span><br /></code></pre></div></div><br class="example-break"></br><p>
      By writing the contract conditions into the tests, we have used
      Design-by-Contract to program the <code class="literal">BankAccount</code> class.
      We then wrote, following the Test-First Programming approach, the
      code needed to make the tests pass. However, we forgot to write
      tests that call <code class="literal">setBalance()</code>,
      <code class="literal">depositMoney()</code>, and <code class="literal">withdrawMoney()</code>
      with legal values that do not violate the contract conditions.
      We need a means to test our tests or at least to measure their quality.
      Such a means is the analysis of code-coverage information that we will
      discuss next.
    </p></div></div>
      <table border="0" width="100%">
        <tr>
          <td align="left"><a accesskey="p" href="testing-practices.html" tppabs="http://www.phpunit.de/manual/current/en/testing-practices.html">Prev</a></td>
          <td align="right"><a accesskey="n" href="behaviour-driven-development.html" tppabs="http://www.phpunit.de/manual/current/en/behaviour-driven-development.html">Next</a></td>
        </tr>
      </table>
    </div>
    <div class="col2">
<dl><dt><span class="chapter"><a href="automating-tests.html" tppabs="http://www.phpunit.de/manual/current/en/automating-tests.html">1. 自动化测试</a></span></dt><dt><span class="chapter"><a href="goals.html" tppabs="http://www.phpunit.de/manual/current/en/goals.html">2. PHPUnit的目标</a></span></dt><dt><span class="chapter"><a href="installation.html" tppabs="http://www.phpunit.de/manual/current/en/installation.html">3. 安装PHPUnit</a></span></dt><dt><span class="chapter"><a href="writing-tests-for-phpunit.html" tppabs="http://www.phpunit.de/manual/current/en/writing-tests-for-phpunit.html">4. 为PHPUnit编写测试</a></span></dt><dd><dl><dt><span class="section"><a href="writing-tests-for-phpunit.html#writing-tests-for-phpunit.data-providers" tppabs="http://www.phpunit.de/manual/current/en/writing-tests-for-phpunit.html#writing-tests-for-phpunit.data-providers">Data Providers</a></span></dt><dt><span class="section"><a href="writing-tests-for-phpunit.html#writing-tests-for-phpunit.exceptions" tppabs="http://www.phpunit.de/manual/current/en/writing-tests-for-phpunit.html#writing-tests-for-phpunit.exceptions">Testing Exceptions</a></span></dt><dt><span class="section"><a href="writing-tests-for-phpunit.html#writing-tests-for-phpunit.errors" tppabs="http://www.phpunit.de/manual/current/en/writing-tests-for-phpunit.html#writing-tests-for-phpunit.errors">Testing PHP Errors</a></span></dt></dl></dd><dt><span class="chapter"><a href="textui.html" tppabs="http://www.phpunit.de/manual/current/en/textui.html">5. The Command-Line Test Runner</a></span></dt><dt><span class="chapter"><a href="fixtures.html" tppabs="http://www.phpunit.de/manual/current/en/fixtures.html">6. Fixtures</a></span></dt><dd><dl><dt><span class="section"><a href="fixtures.html#fixtures.more-setup-than-teardown" tppabs="http://www.phpunit.de/manual/current/en/fixtures.html#fixtures.more-setup-than-teardown">More setUp() than tearDown()</a></span></dt><dt><span class="section"><a href="fixtures.html#fixtures.variations" tppabs="http://www.phpunit.de/manual/current/en/fixtures.html#fixtures.variations">Variations</a></span></dt><dt><span class="section"><a href="fixtures.html#fixtures.sharing-fixture" tppabs="http://www.phpunit.de/manual/current/en/fixtures.html#fixtures.sharing-fixture">Sharing Fixture</a></span></dt><dt><span class="section"><a href="fixtures.html#fixtures.global-state" tppabs="http://www.phpunit.de/manual/current/en/fixtures.html#fixtures.global-state">Global State</a></span></dt></dl></dd><dt><span class="chapter"><a href="organizing-tests.html" tppabs="http://www.phpunit.de/manual/current/en/organizing-tests.html">7. Organizing Tests</a></span></dt><dd><dl><dt><span class="section"><a href="organizing-tests.html#organizing-tests.filesystem" tppabs="http://www.phpunit.de/manual/current/en/organizing-tests.html#organizing-tests.filesystem">Composing a Test Suite Using the Filesystem</a></span></dt><dt><span class="section"><a href="organizing-tests.html#organizing-tests.xml-configuration" tppabs="http://www.phpunit.de/manual/current/en/organizing-tests.html#organizing-tests.xml-configuration">Composing a Test Suite Using XML Configuration</a></span></dt><dt><span class="section"><a href="organizing-tests.html#organizing-tests.testsuite" tppabs="http://www.phpunit.de/manual/current/en/organizing-tests.html#organizing-tests.testsuite">Using the TestSuite Class</a></span></dt></dl></dd><dt><span class="chapter"><a href="testcase-extensions.html" tppabs="http://www.phpunit.de/manual/current/en/testcase-extensions.html">8. TestCase Extensions</a></span></dt><dd><dl><dt><span class="section"><a href="testcase-extensions.html#testcase-extensions.output" tppabs="http://www.phpunit.de/manual/current/en/testcase-extensions.html#testcase-extensions.output">Testing Output</a></span></dt><dt><span class="section"><a href="testcase-extensions.html#testcase-extensions.performance" tppabs="http://www.phpunit.de/manual/current/en/testcase-extensions.html#testcase-extensions.performance">Testing Performance</a></span></dt></dl></dd><dt><span class="chapter"><a href="database.html" tppabs="http://www.phpunit.de/manual/current/en/database.html">9. Database Testing</a></span></dt><dd><dl><dt><span class="section"><a href="database.html#database.datasets" tppabs="http://www.phpunit.de/manual/current/en/database.html#database.datasets">Data Sets</a></span></dt><dd><dl><dt><span class="section"><a href="database.html#database.datasets.flatxml" tppabs="http://www.phpunit.de/manual/current/en/database.html#database.datasets.flatxml">Flat XML Data Set</a></span></dt><dt><span class="section"><a href="database.html#database.datasets.xml" tppabs="http://www.phpunit.de/manual/current/en/database.html#database.datasets.xml">XML Data Set</a></span></dt><dt><span class="section"><a href="database.html#database.datasets.csv" tppabs="http://www.phpunit.de/manual/current/en/database.html#database.datasets.csv">CSV Data Set</a></span></dt><dt><span class="section"><a href="database.html#database.datasets.replacement" tppabs="http://www.phpunit.de/manual/current/en/database.html#database.datasets.replacement">Replacement Data Set</a></span></dt></dl></dd><dt><span class="section"><a href="database.html#database.operations" tppabs="http://www.phpunit.de/manual/current/en/database.html#database.operations">Operations</a></span></dt><dt><span class="section"><a href="database.html#database.bestpractices" tppabs="http://www.phpunit.de/manual/current/en/database.html#database.bestpractices">Database Testing Best Practices</a></span></dt></dl></dd><dt><span class="chapter"><a href="incomplete-and-skipped-tests.html" tppabs="http://www.phpunit.de/manual/current/en/incomplete-and-skipped-tests.html">10. Incomplete and Skipped Tests</a></span></dt><dd><dl><dt><span class="section"><a href="incomplete-and-skipped-tests.html#incomplete-and-skipped-tests.incomplete-tests" tppabs="http://www.phpunit.de/manual/current/en/incomplete-and-skipped-tests.html#incomplete-and-skipped-tests.incomplete-tests">Incomplete Tests</a></span></dt><dt><span class="section"><a href="incomplete-and-skipped-tests.html#incomplete-and-skipped-tests.skipping-tests" tppabs="http://www.phpunit.de/manual/current/en/incomplete-and-skipped-tests.html#incomplete-and-skipped-tests.skipping-tests">Skipping Tests</a></span></dt></dl></dd><dt><span class="chapter"><a href="test-doubles.html" tppabs="http://www.phpunit.de/manual/current/en/test-doubles.html">11. Test Doubles</a></span></dt><dd><dl><dt><span class="section"><a href="test-doubles.html#test-doubles.stubs" tppabs="http://www.phpunit.de/manual/current/en/test-doubles.html#test-doubles.stubs">Stubs</a></span></dt><dt><span class="section"><a href="test-doubles.html#test-doubles.mock-objects" tppabs="http://www.phpunit.de/manual/current/en/test-doubles.html#test-doubles.mock-objects">Mock Objects</a></span></dt><dt><span class="section"><a href="test-doubles.html#test-doubles.mocking-the-filesystem" tppabs="http://www.phpunit.de/manual/current/en/test-doubles.html#test-doubles.mocking-the-filesystem">Mocking the Filesystem</a></span></dt></dl></dd><dt><span class="chapter"><a href="testing-practices.html" tppabs="http://www.phpunit.de/manual/current/en/testing-practices.html">12. Testing Practices</a></span></dt><dd><dl><dt><span class="section"><a href="testing-practices.html#testing-practices.during-development" tppabs="http://www.phpunit.de/manual/current/en/testing-practices.html#testing-practices.during-development">During Development</a></span></dt><dt><span class="section"><a href="testing-practices.html#testing-practices.during-debugging" tppabs="http://www.phpunit.de/manual/current/en/testing-practices.html#testing-practices.during-debugging">During Debugging</a></span></dt></dl></dd><dt><span class="chapter"><a href="test-driven-development.html" tppabs="http://www.phpunit.de/manual/current/en/test-driven-development.html" class="active">13. Test-Driven Development</a></span></dt><dd><dl><dt><span class="section"><a href="test-driven-development.html#test-driven-development.bankaccount-example" tppabs="http://www.phpunit.de/manual/current/en/test-driven-development.html#test-driven-development.bankaccount-example">BankAccount Example</a></span></dt></dl></dd><dt><span class="chapter"><a href="behaviour-driven-development.html" tppabs="http://www.phpunit.de/manual/current/en/behaviour-driven-development.html">14. Behaviour-Driven Development</a></span></dt><dd><dl><dt><span class="section"><a href="behaviour-driven-development.html#behaviour-driven-development.bowlinggame-example" tppabs="http://www.phpunit.de/manual/current/en/behaviour-driven-development.html#behaviour-driven-development.bowlinggame-example">BowlingGame Example</a></span></dt></dl></dd><dt><span class="chapter"><a href="code-coverage-analysis.html" tppabs="http://www.phpunit.de/manual/current/en/code-coverage-analysis.html">15. Code Coverage Analysis</a></span></dt><dd><dl><dt><span class="section"><a href="code-coverage-analysis.html#code-coverage-analysis.specifying-covered-methods" tppabs="http://www.phpunit.de/manual/current/en/code-coverage-analysis.html#code-coverage-analysis.specifying-covered-methods">Specifying Covered Methods</a></span></dt><dt><span class="section"><a href="code-coverage-analysis.html#code-coverage-analysis.ignoring-code-blocks" tppabs="http://www.phpunit.de/manual/current/en/code-coverage-analysis.html#code-coverage-analysis.ignoring-code-blocks">Ignoring Code Blocks</a></span></dt><dt><span class="section"><a href="code-coverage-analysis.html#code-coverage-analysis.including-excluding-files" tppabs="http://www.phpunit.de/manual/current/en/code-coverage-analysis.html#code-coverage-analysis.including-excluding-files">Including and Excluding Files</a></span></dt></dl></dd><dt><span class="chapter"><a href="other-uses-for-tests.html" tppabs="http://www.phpunit.de/manual/current/en/other-uses-for-tests.html">16. Other Uses for Tests</a></span></dt><dd><dl><dt><span class="section"><a href="other-uses-for-tests.html#other-uses-for-tests.agile-documentation" tppabs="http://www.phpunit.de/manual/current/en/other-uses-for-tests.html#other-uses-for-tests.agile-documentation">Agile Documentation</a></span></dt><dt><span class="section"><a href="other-uses-for-tests.html#other-uses-for-tests.cross-team-tests" tppabs="http://www.phpunit.de/manual/current/en/other-uses-for-tests.html#other-uses-for-tests.cross-team-tests">Cross-Team Tests</a></span></dt></dl></dd><dt><span class="chapter"><a href="skeleton-generator.html" tppabs="http://www.phpunit.de/manual/current/en/skeleton-generator.html">17. Skeleton Generator</a></span></dt><dd><dl><dt><span class="section"><a href="skeleton-generator.html#skeleton-generator.test" tppabs="http://www.phpunit.de/manual/current/en/skeleton-generator.html#skeleton-generator.test">Generating a Test Case Class Skeleton</a></span></dt><dt><span class="section"><a href="skeleton-generator.html#skeleton-generator.class" tppabs="http://www.phpunit.de/manual/current/en/skeleton-generator.html#skeleton-generator.class">Generating a Class Skeleton from a Test Case Class</a></span></dt></dl></dd><dt><span class="chapter"><a href="javascript:if(confirm('http://www.phpunit.de/manual/current/en/selenium.html  \n\nļδ Teleport Pro ȡأΪ ޷ȡãȡغĿֹ̫ͣ졣  \n\nҪӷϴ'))window.location='http://www.phpunit.de/manual/current/en/selenium.html'" tppabs="http://www.phpunit.de/manual/current/en/selenium.html">18. PHPUnit and Selenium</a></span></dt><dd><dl><dt><span class="section"><a href="javascript:if(confirm('http://www.phpunit.de/manual/current/en/selenium.html  \n\nļδ Teleport Pro ȡأΪ ޷ȡãȡغĿֹ̫ͣ졣  \n\nҪӷϴ'))window.location='http://www.phpunit.de/manual/current/en/selenium.html#selenium.selenium-rc'" tppabs="http://www.phpunit.de/manual/current/en/selenium.html#selenium.selenium-rc">Selenium RC</a></span></dt><dt><span class="section"><a href="javascript:if(confirm('http://www.phpunit.de/manual/current/en/selenium.html  \n\nļδ Teleport Pro ȡأΪ ޷ȡãȡغĿֹ̫ͣ졣  \n\nҪӷϴ'))window.location='http://www.phpunit.de/manual/current/en/selenium.html#selenium.seleniumtestcase'" tppabs="http://www.phpunit.de/manual/current/en/selenium.html#selenium.seleniumtestcase">PHPUnit_Extensions_SeleniumTestCase</a></span></dt></dl></dd><dt><span class="chapter"><a href="logging.html" tppabs="http://www.phpunit.de/manual/current/en/logging.html">19. Logging</a></span></dt><dd><dl><dt><span class="section"><a href="logging.html#logging.xml" tppabs="http://www.phpunit.de/manual/current/en/logging.html#logging.xml">Test Results (XML)</a></span></dt><dt><span class="section"><a href="logging.html#logging.tap" tppabs="http://www.phpunit.de/manual/current/en/logging.html#logging.tap">Test Results (TAP)</a></span></dt><dt><span class="section"><a href="logging.html#logging.json" tppabs="http://www.phpunit.de/manual/current/en/logging.html#logging.json">Test Results (JSON)</a></span></dt><dt><span class="section"><a href="logging.html#logging.codecoverage" tppabs="http://www.phpunit.de/manual/current/en/logging.html#logging.codecoverage">Code Coverage (XML)</a></span></dt><dt><span class="section"><a href="logging.html#logging.database" tppabs="http://www.phpunit.de/manual/current/en/logging.html#logging.database">Test Database</a></span></dt></dl></dd><dt><span class="chapter"><a href="build-automation.html" tppabs="http://www.phpunit.de/manual/current/en/build-automation.html">20. Build Automation</a></span></dt><dd><dl><dt><span class="section"><a href="build-automation.html#build-automation.ant" tppabs="http://www.phpunit.de/manual/current/en/build-automation.html#build-automation.ant">Apache Ant</a></span></dt><dt><span class="section"><a href="build-automation.html#build-automation.maven" tppabs="http://www.phpunit.de/manual/current/en/build-automation.html#build-automation.maven">Apache Maven</a></span></dt><dt><span class="section"><a href="build-automation.html#build-automation.phing" tppabs="http://www.phpunit.de/manual/current/en/build-automation.html#build-automation.phing">Phing</a></span></dt></dl></dd><dt><span class="chapter"><a href="continuous-integration.html" tppabs="http://www.phpunit.de/manual/current/en/continuous-integration.html">21. Continuous Integration</a></span></dt><dd><dl><dt><span class="section"><a href="continuous-integration.html#continuous-integration.atlassian-bamboo" tppabs="http://www.phpunit.de/manual/current/en/continuous-integration.html#continuous-integration.atlassian-bamboo">Atlassian Bamboo</a></span></dt><dt><span class="section"><a href="continuous-integration.html#continuous-integration.cruisecontrol" tppabs="http://www.phpunit.de/manual/current/en/continuous-integration.html#continuous-integration.cruisecontrol">CruiseControl</a></span></dt><dt><span class="section"><a href="continuous-integration.html#continuous-integration.phpUnderControl" tppabs="http://www.phpunit.de/manual/current/en/continuous-integration.html#continuous-integration.phpUnderControl">phpUnderControl</a></span></dt></dl></dd><dt><span class="chapter"><a href="api.html" tppabs="http://www.phpunit.de/manual/current/en/api.html">22. PHPUnit API</a></span></dt><dd><dl><dt><span class="section"><a href="api.html#api.overview" tppabs="http://www.phpunit.de/manual/current/en/api.html#api.overview">Overview</a></span></dt><dt><span class="section"><a href="api.html#api.assert" tppabs="http://www.phpunit.de/manual/current/en/api.html#api.assert">PHPUnit_Framework_Assert</a></span></dt><dd><dl><dt><span class="section"><a href="api.html#api.assert.assertArrayHasKey" tppabs="http://www.phpunit.de/manual/current/en/api.html#api.assert.assertArrayHasKey"><code class="literal">assertArrayHasKey()</code></a></span></dt><dt><span class="section"><a href="api.html#api.assert.assertClassHasAttribute" tppabs="http://www.phpunit.de/manual/current/en/api.html#api.assert.assertClassHasAttribute"><code class="literal">assertClassHasAttribute()</code></a></span></dt><dt><span class="section"><a href="api.html#api.assert.assertClassHasStaticAttribute" tppabs="http://www.phpunit.de/manual/current/en/api.html#api.assert.assertClassHasStaticAttribute"><code class="literal">assertClassHasStaticAttribute()</code></a></span></dt><dt><span class="section"><a href="api.html#api.assert.assertContains" tppabs="http://www.phpunit.de/manual/current/en/api.html#api.assert.assertContains"><code class="literal">assertContains()</code></a></span></dt><dt><span class="section"><a href="api.html#api.assert.assertContainsOnly" tppabs="http://www.phpunit.de/manual/current/en/api.html#api.assert.assertContainsOnly"><code class="literal">assertContainsOnly()</code></a></span></dt><dt><span class="section"><a href="api.html#api.assert.assertEqualXMLStructure" tppabs="http://www.phpunit.de/manual/current/en/api.html#api.assert.assertEqualXMLStructure"><code class="literal">assertEqualXMLStructure()</code></a></span></dt><dt><span class="section"><a href="api.html#api.assert.assertEquals" tppabs="http://www.phpunit.de/manual/current/en/api.html#api.assert.assertEquals"><code class="literal">assertEquals()</code></a></span></dt><dt><span class="section"><a href="api.html#api.assert.assertFalse" tppabs="http://www.phpunit.de/manual/current/en/api.html#api.assert.assertFalse"><code class="literal">assertFalse()</code></a></span></dt><dt><span class="section"><a href="api.html#api.assert.assertFileEquals" tppabs="http://www.phpunit.de/manual/current/en/api.html#api.assert.assertFileEquals"><code class="literal">assertFileEquals()</code></a></span></dt><dt><span class="section"><a href="api.html#api.assert.assertFileExists" tppabs="http://www.phpunit.de/manual/current/en/api.html#api.assert.assertFileExists"><code class="literal">assertFileExists()</code></a></span></dt><dt><span class="section"><a href="api.html#api.assert.assertGreaterThan" tppabs="http://www.phpunit.de/manual/current/en/api.html#api.assert.assertGreaterThan"><code class="literal">assertGreaterThan()</code></a></span></dt><dt><span class="section"><a href="api.html#api.assert.assertGreaterThanOrEqual" tppabs="http://www.phpunit.de/manual/current/en/api.html#api.assert.assertGreaterThanOrEqual"><code class="literal">assertGreaterThanOrEqual()</code></a></span></dt><dt><span class="section"><a href="api.html#api.assert.assertLessThan" tppabs="http://www.phpunit.de/manual/current/en/api.html#api.assert.assertLessThan"><code class="literal">assertLessThan()</code></a></span></dt><dt><span class="section"><a href="api.html#api.assert.assertLessThanOrEqual" tppabs="http://www.phpunit.de/manual/current/en/api.html#api.assert.assertLessThanOrEqual"><code class="literal">assertLessThanOrEqual()</code></a></span></dt><dt><span class="section"><a href="api.html#api.assert.assertNotNull" tppabs="http://www.phpunit.de/manual/current/en/api.html#api.assert.assertNotNull"><code class="literal">assertNotNull()</code></a></span></dt><dt><span class="section"><a href="api.html#api.assert.assertObjectHasAttribute" tppabs="http://www.phpunit.de/manual/current/en/api.html#api.assert.assertObjectHasAttribute"><code class="literal">assertObjectHasAttribute()</code></a></span></dt><dt><span class="section"><a href="api.html#api.assert.assertRegExp" tppabs="http://www.phpunit.de/manual/current/en/api.html#api.assert.assertRegExp"><code class="literal">assertRegExp()</code></a></span></dt><dt><span class="section"><a href="api.html#api.assert.assertSame" tppabs="http://www.phpunit.de/manual/current/en/api.html#api.assert.assertSame"><code class="literal">assertSame()</code></a></span></dt><dt><span class="section"><a href="api.html#api.assert.assertSelectCount" tppabs="http://www.phpunit.de/manual/current/en/api.html#api.assert.assertSelectCount"><code class="literal">assertSelectCount()</code></a></span></dt><dt><span class="section"><a href="api.html#api.assert.assertSelectEquals" tppabs="http://www.phpunit.de/manual/current/en/api.html#api.assert.assertSelectEquals"><code class="literal">assertSelectEquals()</code></a></span></dt><dt><span class="section"><a href="api.html#api.assert.assertSelectRegExp" tppabs="http://www.phpunit.de/manual/current/en/api.html#api.assert.assertSelectRegExp"><code class="literal">assertSelectRegExp()</code></a></span></dt><dt><span class="section"><a href="api.html#api.assert.assertStringEqualsFile" tppabs="http://www.phpunit.de/manual/current/en/api.html#api.assert.assertStringEqualsFile"><code class="literal">assertStringEqualsFile()</code></a></span></dt><dt><span class="section"><a href="api.html#api.assert.assertTag" tppabs="http://www.phpunit.de/manual/current/en/api.html#api.assert.assertTag"><code class="literal">assertTag()</code></a></span></dt><dt><span class="section"><a href="api.html#api.assert.assertThat" tppabs="http://www.phpunit.de/manual/current/en/api.html#api.assert.assertThat"><code class="literal">assertThat()</code></a></span></dt><dt><span class="section"><a href="api.html#api.assert.assertTrue" tppabs="http://www.phpunit.de/manual/current/en/api.html#api.assert.assertTrue"><code class="literal">assertTrue()</code></a></span></dt><dt><span class="section"><a href="api.html#api.assert.assertType" tppabs="http://www.phpunit.de/manual/current/en/api.html#api.assert.assertType"><code class="literal">assertType()</code></a></span></dt><dt><span class="section"><a href="api.html#api.assert.assertXmlFileEqualsXmlFile" tppabs="http://www.phpunit.de/manual/current/en/api.html#api.assert.assertXmlFileEqualsXmlFile"><code class="literal">assertXmlFileEqualsXmlFile()</code></a></span></dt><dt><span class="section"><a href="api.html#api.assert.assertXmlStringEqualsXmlFile" tppabs="http://www.phpunit.de/manual/current/en/api.html#api.assert.assertXmlStringEqualsXmlFile"><code class="literal">assertXmlStringEqualsXmlFile()</code></a></span></dt><dt><span class="section"><a href="api.html#api.assert.assertXmlStringEqualsXmlString" tppabs="http://www.phpunit.de/manual/current/en/api.html#api.assert.assertXmlStringEqualsXmlString"><code class="literal">assertXmlStringEqualsXmlString()</code></a></span></dt></dl></dd><dt><span class="section"><a href="api.html#api.test" tppabs="http://www.phpunit.de/manual/current/en/api.html#api.test">PHPUnit_Framework_Test</a></span></dt><dt><span class="section"><a href="api.html#api.testcase" tppabs="http://www.phpunit.de/manual/current/en/api.html#api.testcase">PHPUnit_Framework_TestCase</a></span></dt><dt><span class="section"><a href="api.html#api.testsuite" tppabs="http://www.phpunit.de/manual/current/en/api.html#api.testsuite">PHPUnit_Framework_TestSuite</a></span></dt><dt><span class="section"><a href="api.html#api.testresult" tppabs="http://www.phpunit.de/manual/current/en/api.html#api.testresult">PHPUnit_Framework_TestResult</a></span></dt><dt><span class="section"><a href="api.html#api.package-structure" tppabs="http://www.phpunit.de/manual/current/en/api.html#api.package-structure">Package Structure</a></span></dt></dl></dd><dt><span class="chapter"><a href="extending-phpunit.html" tppabs="http://www.phpunit.de/manual/current/en/extending-phpunit.html">23. Extending PHPUnit</a></span></dt><dd><dl><dt><span class="section"><a href="extending-phpunit.html#extending-phpunit.PHPUnit_Framework_TestCase" tppabs="http://www.phpunit.de/manual/current/en/extending-phpunit.html#extending-phpunit.PHPUnit_Framework_TestCase">Subclass PHPUnit_Framework_TestCase</a></span></dt><dt><span class="section"><a href="extending-phpunit.html#extending-phpunit.Assert" tppabs="http://www.phpunit.de/manual/current/en/extending-phpunit.html#extending-phpunit.Assert">Assert Classes</a></span></dt><dt><span class="section"><a href="extending-phpunit.html#extending-phpunit.PHPUnit_Extensions_TestDecorator" tppabs="http://www.phpunit.de/manual/current/en/extending-phpunit.html#extending-phpunit.PHPUnit_Extensions_TestDecorator">Subclass PHPUnit_Extensions_TestDecorator</a></span></dt><dt><span class="section"><a href="extending-phpunit.html#extending-phpunit.PHPUnit_Framework_Test" tppabs="http://www.phpunit.de/manual/current/en/extending-phpunit.html#extending-phpunit.PHPUnit_Framework_Test">Implement PHPUnit_Framework_Test</a></span></dt><dt><span class="section"><a href="extending-phpunit.html#extending-phpunit.PHPUnit_Framework_TestResult" tppabs="http://www.phpunit.de/manual/current/en/extending-phpunit.html#extending-phpunit.PHPUnit_Framework_TestResult">Subclass PHPUnit_Framework_TestResult</a></span></dt><dt><span class="section"><a href="extending-phpunit.html#extending-phpunit.PHPUnit_Framework_TestListener" tppabs="http://www.phpunit.de/manual/current/en/extending-phpunit.html#extending-phpunit.PHPUnit_Framework_TestListener">Implement PHPUnit_Framework_TestListener</a></span></dt><dt><span class="section"><a href="extending-phpunit.html#extending-phpunit.TestRunner" tppabs="http://www.phpunit.de/manual/current/en/extending-phpunit.html#extending-phpunit.TestRunner">New Test Runner</a></span></dt></dl></dd><dt><span class="appendix"><a href="appendixes.assertions.html" tppabs="http://www.phpunit.de/manual/current/en/appendixes.assertions.html">A. Assertions</a></span></dt><dt><span class="appendix"><a href="appendixes.configuration.html" tppabs="http://www.phpunit.de/manual/current/en/appendixes.configuration.html">B. The XML Configuration File</a></span></dt><dd><dl><dt><span class="section"><a href="appendixes.configuration.html#appendixes.configuration.phpunit" tppabs="http://www.phpunit.de/manual/current/en/appendixes.configuration.html#appendixes.configuration.phpunit">PHPUnit</a></span></dt><dt><span class="section"><a href="appendixes.configuration.html#appendixes.configuration.testsuite" tppabs="http://www.phpunit.de/manual/current/en/appendixes.configuration.html#appendixes.configuration.testsuite">Test Suite</a></span></dt><dt><span class="section"><a href="appendixes.configuration.html#appendixes.configuration.groups" tppabs="http://www.phpunit.de/manual/current/en/appendixes.configuration.html#appendixes.configuration.groups">Groups</a></span></dt><dt><span class="section"><a href="appendixes.configuration.html#appendixes.configuration.blacklist-whitelist" tppabs="http://www.phpunit.de/manual/current/en/appendixes.configuration.html#appendixes.configuration.blacklist-whitelist">Including and Excluding Files for Code Coverage</a></span></dt><dt><span class="section"><a href="appendixes.configuration.html#appendixes.configuration.logging" tppabs="http://www.phpunit.de/manual/current/en/appendixes.configuration.html#appendixes.configuration.logging">Logging</a></span></dt><dt><span class="section"><a href="appendixes.configuration.html#appendixes.configuration.php-ini-constants-variables" tppabs="http://www.phpunit.de/manual/current/en/appendixes.configuration.html#appendixes.configuration.php-ini-constants-variables">Setting PHP INI settings, Constants and Global Variables</a></span></dt><dt><span class="section"><a href="appendixes.configuration.html#appendixes.configuration.selenium-rc" tppabs="http://www.phpunit.de/manual/current/en/appendixes.configuration.html#appendixes.configuration.selenium-rc">Configuring Browsers for Selenium RC</a></span></dt></dl></dd><dt><span class="appendix"><a href="appendixes.index.html" tppabs="http://www.phpunit.de/manual/current/en/appendixes.index.html">C. Index</a></span></dt><dd><dl><dt><span class="index"><a href="appendixes.index.html#appendixes.index.index" tppabs="http://www.phpunit.de/manual/current/en/appendixes.index.html#appendixes.index.index"></a></span></dt></dl></dd><dt><span class="appendix"><a href="appendixes.bibliography.html" tppabs="http://www.phpunit.de/manual/current/en/appendixes.bibliography.html">D. Bibliography</a></span></dt><dt><span class="appendix"><a href="appendixes.copyright.html" tppabs="http://www.phpunit.de/manual/current/en/appendixes.copyright.html">E. Copyright</a></span></dt></dl>
    </div>
  </div>
</div>
<div id="footer">
  <p><a href="appendixes.copyright.html" tppabs="http://www.phpunit.de/manual/current/en/appendixes.copyright.html">Copyright</a> &copy; 2005-2009 <a href="javascript:if(confirm('http://sebastian-bergmann.de/  \n\nļδ Teleport Pro ȡأΪ ·ʼַõķΧ  \n\nҪӷϴ'))window.location='http://sebastian-bergmann.de/'" tppabs="http://sebastian-bergmann.de/">Sebastian Bergmann</a>.</p>
</div>
<script type="text/javascript">
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www./");
document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
</script>
<script type="text/javascript">
try {
var pageTracker = _gat._getTracker("UA-68261-7");
pageTracker._trackPageview();
} catch(err) {}</script>
</body>
</html>

